<?php
declare (strict_types=1);

namespace app\user\logic\user\admin;

use app\admin\logic\system\Log;
use app\common\exception\LogicException;
use app\common\library\Excel;
use app\common\logic\Attach;
use app\school\model\school\School;
use app\user\model\user\admin\Account as AccountModel;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Request;
use think\Model;

class Account extends AccountModel
{
    /**
     * 用户列表
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-13
     */
    public function getUserList(array $map = [])
    {
        return $this->with(['avatarUrl', 'school'])->where($map)->order('update_time', 'DESC')->paginate($this->getListRows());
    }

    /**
     * 添加用户
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-03
     *
     * @param array $data 数据
     * @return \app\user\logic\user\Account
     */
    public function addUser(array $data)
    {
        // 验证数据
        $this->getValidate()->scene('add')->failException()->check($data);

        if (!$this->data($data, true)->save()) {
            throw new LogicException('登录失败', '注册失败');
        }

        return $this;
    }

    /**
     * 编辑用户
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-04
     *
     * @param array $data 数据
     * @return    \app\user\logic\user\Account
     */
    public function editUser(array $data)
    {
        // 用户是否存在
        $user = $this->where('id', $data['id'])->findOrFail();
        // 取得验证器
        $this->getValidate()->scene('edit')->failException()->check($data);

        $update = [
            // 'status'    => $data['status'] ?? 1,
            'phone'     => $data['phone'],
            'nick_name' => $data['nick_name'],
            'best_sort' => $data['best_sort'] ?? 1,
        ];

        $data['password'] && $update['password'] = $data['password'];

        if (!$user->update($update, ['id' => $data['id']])) {
            throw new LogicException('编辑失败');
        }

        return $user;
    }

    /**
     * 注销用户
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-03
     *
     * @param int $id 删除用户ID
     * @return   boolean 是否删除成功
     */
    public function deleteUser(int $id): bool
    {
        $user              = $this->where('id', $id)->findOrFail();
        $user->user_name   .= '_' . $id;
        $user->phone       .= '_' . $id;
        $user->delete_time = time();
        return $user->save();
    }

    /**
     * 更新用户账号状态
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-05-07
     *
     * @param int $id     [description]
     * @param int $status [description]
     * @return Account|array|Model [type]                                 [description]
     */
    public function updateStatus(int $id, int $status = 1)
    {
        $user = $this->where('id', $id)->findOrFail();

        $user->status = $status;

        if (!$user->save()) {
            throw new LogicException("操作失败");

        }

        return $user;

    }

    public function getUserNickName($user_id = 0)
    {
        return $this->where('id', $user_id)->value('nick_name');
    }

    /**
     * 批量更新数据
     *
     * @param array  $ids
     * @param string $field
     * @param        $value
     */
    public function batchUpdated(array $ids, string $field, $value)
    {
        $ret = AccountModel::update([$field => $value], [['id', 'in', $ids]]);
        if (!$ret) {
            throw new LogicException('批量操作失败');
        }
    }

    /**
     * 批量删除
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/10/16
     *
     * @param $ids
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function deleteUsers($ids): void
    {
        $this->whereIn('id', $ids)->select()->each(function ($u) {
            $u->user_name   .= '_' . $u->id;
            $u->phone       .= '_' . $u->id;
            $u->delete_time = time();
            if (!$u->save()) throw new LogicException('操作失败');
        });
    }

    public function doImportStudent(int $attach_id)
    {
        // 获取附件信息
        $attach = Attach::where('id', $attach_id)->findOrEmpty();
        if ($attach->isEmpty()) {
            throw new LogicException('附件不存在，请重新上传');
        }

        $filepath = $attach->filepath;
        if (!is_file($filepath)) {
            throw new LogicException('附件不存在，请重新上传');

        }
        // 加载附件内容
        $data = Excel::import($filepath);
        // 第一行为标题
        unset($data[0]);
        // 单次最多导入1000条数据
        $importCount = count($data);
        if ($importCount > 1000) {
            throw new LogicException('单次最多导入1000条数据');
        }

        $total   = 0;
        $errors  = [];
        $inserts = [];
        $mhms    = [];
        $gender  = ['保密' => 0, '男' => 1, '女' => 2];
        $time    = Request::time();
        $ip      = Request::ip();
        // 检查数据是否正确,检测到错误数量大于等于10时,停止检测,抛出错误
        foreach ($data as $k => $user) {
            $row = $k;// + 1;
            if ($total >= 10) {
                break;
            }
            // 处理office读取数据问题
            if (!$user[0] && !$user[1] && !$user[2] && !$user[3] && !$user[4] && !$user[5] && !$user[6]) continue;

            // 手机号或则机构未配置
            if (!$user[0] || !$user[1]) {
                $total    += 1;
                $errors[] = '第' . $row . '行: 手机号或所属机构不能为空值';
                continue;
            }
            // 检验所属的机构是否存在
            if (!isset($mhms[$user[1]])) {
                $mhm_id = School::where('school_code', $user[1])->value('id');
                if (!$mhm_id) {
                    $total    += 1;
                    $errors[] = '第' . $row . '行: 指定的所属机构不存在';
                    continue;
                }
                $mhms[$user[1]] = $mhm_id;
            } else {
                $mhm_id = $mhms[$user[1]];
            }
            // 检测用户名是否重复
            $exist = Account::where('user_name', $user[2])->value('id');
            if ($exist) {
                $total    += 1;
                $errors[] = '第' . $row . '行: 指定的用户名已存在';
                continue;
            }

            // 数据无误,直接组装
            $item = [
                'mhm_id'          => $mhm_id,
                'user_name'       => $user[2] ?? '',
                'nick_name'       => $user[3] ?? $user[0],
                'gender'          => $gender[$user[5]] ?? 0,
                'status'          => $user[6] == '禁用' ? 0 : 1,
                'register_device' => 'admin',
                'register_ip'     => $ip,
                'create_time'     => $time,
                'update_time'     => $time,
                'phone'           => $user[0],
            ];
            // 是否有密码
            if ($user[4]) {
                $password         = md5((string)$user[4]);
                $model            = new AccountModel();
                $salt             = $model->setSaltAttr('', []);
                $item['password'] = $model->makePassword($password, $salt);
                $item['salt']     = $salt;
            } else {
                $item['password'] = '';
                $item['salt']     = '';
            }

            $inserts[] = $item;
        }
        // 数据有误,返回错误
        if ($total > 0) {
            return ['status' => 0, 'errors' => $errors];
        }
        // 开始导入数据
        $success = $this->extra('IGNORE')->insertAll($inserts, 250);
        if ($success == 0) {
            throw new LogicException("导入失败，请检查是否重复导入");
        }

        Log::write('导入学员', 'user_account', 'import', true);

        // $users = $this->where('id', '>', $max)->limit($success)->column('user_id');

        return [
            'status'  => 1,
            'total'   => $importCount,
            'success' => $success,
            'exists'  => $importCount - $success,
        ];
    }

    /**
     * 搜索学生
     *
     * @param string $keyword
     * @param int    $limit
     * @return Account[]|array|Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function searchStudent(string $keyword, int $limit = 10)
    {
        return $this->where('nick_name', 'like', '%' . $keyword . '%')
            ->whereOr('phone', 'like', '%' . $keyword . '%')
            ->field(['id' => 'value', 'nick_name', 'phone'])
            ->limit($limit)
            ->select()
            ->hidden(['phone', 'nick_name'])
            ->each(function ($item) {
                $phone = '';
                if ($item->phone) {
                    $phone = '（' . $item->phone . '）';
                }
                $item->title = $item->nick_name . $phone;
            });
    }

}
